use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::Json,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::task;

use crate::database::{Bookmark, Conversation, KnowledgeItem, Message};
use crate::vector_search::SearchResult;
use crate::AppState;

// Request/Response structs for conversations
#[derive(Deserialize)]
pub struct CreateConversationRequest {
    pub title: String,
    pub agent_id: Option<i64>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct CreateConversationResponse {
    pub id: i64,
    pub message: String,
}

#[derive(Deserialize)]
pub struct UpdateConversationRequest {
    pub title: Option<String>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct ConversationListResponse {
    pub conversations: Vec<Conversation>,
    pub total: usize,
}

#[derive(Serialize)]
pub struct DeleteResponse {
    pub success: bool,
    pub message: String,
}

// Request/Response structs for messages
#[derive(Deserialize)]
pub struct CreateMessageRequest {
    pub role: String,
    pub content: String,
    pub status: Option<String>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct CreateMessageResponse {
    pub id: i64,
    pub message: String,
}

#[derive(Deserialize)]
pub struct UpdateMessageRequest {
    pub content: Option<String>,
    pub status: Option<String>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct MessageListResponse {
    pub messages: Vec<Message>,
    pub total: usize,
}

// Request/Response structs for bookmarks
#[derive(Deserialize)]
pub struct CreateBookmarkRequest {
    pub title: String,
    pub prompt: String,
    pub description: Option<String>,
    pub category: Option<String>,
    pub tags: Option<Vec<String>>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct CreateBookmarkResponse {
    pub id: i64,
    pub message: String,
}

#[derive(Deserialize)]
pub struct UpdateBookmarkRequest {
    pub title: Option<String>,
    pub prompt: Option<String>,
    pub description: Option<String>,
    pub category: Option<String>,
    pub tags: Option<Vec<String>>,
    pub metadata: Option<serde_json::Value>,
}

#[derive(Serialize)]
pub struct BookmarkListResponse {
    pub bookmarks: Vec<Bookmark>,
    pub total: usize,
}

// Request/Response structs for knowledge items
#[derive(Deserialize)]
pub struct CreateKnowledgeItemRequest {
    pub title: String,
    pub content: Option<String>,
    pub item_type: String, // "document", "url", "text"
    pub url: Option<String>,
    pub file_path: Option<String>,
    pub file_size: Option<i64>,
    pub mime_type: Option<String>,
    pub tags: Option<Vec<String>>,
    pub metadata: Option<serde_json::Value>,
    pub agent_id: Option<i64>, // Agent ID for embedding configuration
}

#[derive(Serialize)]
pub struct CreateKnowledgeItemResponse {
    pub id: i64,
    pub message: String,
}

#[derive(Serialize)]
pub struct KnowledgeItemListResponse {
    pub items: Vec<KnowledgeItem>,
    pub total: usize,
}

// Query parameters
#[derive(Deserialize)]
pub struct PaginationQuery {
    pub limit: Option<i64>,
    pub offset: Option<i64>,
}

#[derive(Deserialize)]
pub struct BookmarkQuery {
    pub limit: Option<i64>,
    pub offset: Option<i64>,
    pub category: Option<String>,
    pub favorites_only: Option<bool>,
}

#[derive(Deserialize)]
pub struct KnowledgeQuery {
    pub limit: Option<i64>,
    pub offset: Option<i64>,
    pub item_type: Option<String>,
}

#[derive(Deserialize)]
pub struct SearchQuery {
    pub q: String,
    pub limit: Option<i64>,
}

// Conversation handlers
pub async fn create_conversation_handler(
    State(state): State<Arc<AppState>>,
    Json(payload): Json<CreateConversationRequest>,
) -> Result<Json<CreateConversationResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.create_conversation(&payload.title, payload.agent_id, metadata_str.as_deref()) {
            Ok(id) => Ok(Json(CreateConversationResponse {
                id,
                message: format!("Conversation '{}' created successfully", payload.title),
            })),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to create conversation: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn get_conversation_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<Conversation>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.get_conversation(id) {
        Ok(Some(conversation)) => Ok(Json(conversation)),
        Ok(None) => Err((
            StatusCode::NOT_FOUND,
            format!("Conversation with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to get conversation: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn list_conversations_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<PaginationQuery>,
) -> Result<Json<ConversationListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.list_conversations(params.limit, params.offset) {
        Ok(conversations) => {
            let total = conversations.len();
            Ok(Json(ConversationListResponse {
                conversations,
                total,
            }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to list conversations: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn update_conversation_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
    Json(payload): Json<UpdateConversationRequest>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.update_conversation(id, payload.title.as_deref(), metadata_str.as_deref()) {
            Ok(true) => Ok(Json(DeleteResponse {
                success: true,
                message: format!("Conversation with id {} updated successfully", id),
            })),
            Ok(false) => Err((
                StatusCode::NOT_FOUND,
                format!("Conversation with id {} not found", id),
            )),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to update conversation: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn delete_conversation_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.delete_conversation(id) {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Conversation with id {} deleted successfully", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Conversation with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to delete conversation: {}", e),
        )),
    })
    .await
    .unwrap()
}

// Message handlers
pub async fn create_message_handler(
    State(state): State<Arc<AppState>>,
    Path(conversation_id): Path<i64>,
    Json(payload): Json<CreateMessageRequest>,
) -> Result<Json<CreateMessageResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.create_message(
            conversation_id,
            &payload.role,
            &payload.content,
            payload.status.as_deref(),
            metadata_str.as_deref(),
        ) {
            Ok(id) => Ok(Json(CreateMessageResponse {
                id,
                message: "Message created successfully".to_string(),
            })),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to create message: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn get_messages_handler(
    State(state): State<Arc<AppState>>,
    Path(conversation_id): Path<i64>,
    Query(params): Query<PaginationQuery>,
) -> Result<Json<MessageListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.get_messages(conversation_id, params.limit, params.offset) {
        Ok(messages) => {
            let total = messages.len();
            Ok(Json(MessageListResponse { messages, total }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to get messages: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn update_message_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
    Json(payload): Json<UpdateMessageRequest>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.update_message(
            id,
            payload.content.as_deref(),
            payload.status.as_deref(),
            metadata_str.as_deref(),
        ) {
            Ok(true) => Ok(Json(DeleteResponse {
                success: true,
                message: format!("Message with id {} updated successfully", id),
            })),
            Ok(false) => Err((
                StatusCode::NOT_FOUND,
                format!("Message with id {} not found", id),
            )),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to update message: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

// Bookmark handlers
pub async fn create_bookmark_handler(
    State(state): State<Arc<AppState>>,
    Json(payload): Json<CreateBookmarkRequest>,
) -> Result<Json<CreateBookmarkResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let tags_str = payload.tags.map(|t| serde_json::to_string(&t).unwrap_or_default());
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.create_bookmark(
            &payload.title,
            &payload.prompt,
            payload.description.as_deref(),
            payload.category.as_deref(),
            tags_str.as_deref(),
            metadata_str.as_deref(),
        ) {
            Ok(id) => Ok(Json(CreateBookmarkResponse {
                id,
                message: format!("Bookmark '{}' created successfully", payload.title),
            })),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to create bookmark: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn get_bookmark_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<Bookmark>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.get_bookmark(id) {
        Ok(Some(bookmark)) => Ok(Json(bookmark)),
        Ok(None) => Err((
            StatusCode::NOT_FOUND,
            format!("Bookmark with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to get bookmark: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn list_bookmarks_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<BookmarkQuery>,
) -> Result<Json<BookmarkListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || {
        match db.list_bookmarks(
            params.category.as_deref(),
            params.favorites_only.unwrap_or(false),
            params.limit,
            params.offset,
        ) {
            Ok(bookmarks) => {
                let total = bookmarks.len();
                Ok(Json(BookmarkListResponse { bookmarks, total }))
            }
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to list bookmarks: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn use_bookmark_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.update_bookmark_usage(id) {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Bookmark usage updated for id {}", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Bookmark with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to update bookmark usage: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn toggle_bookmark_favorite_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.toggle_bookmark_favorite(id) {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Bookmark favorite status toggled for id {}", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Bookmark with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to toggle bookmark favorite: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn delete_bookmark_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.delete_bookmark(id) {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Bookmark with id {} deleted successfully", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Bookmark with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to delete bookmark: {}", e),
        )),
    })
    .await
    .unwrap()
}

// Knowledge item handlers
pub async fn create_knowledge_item_handler(
    State(state): State<Arc<AppState>>,
    Json(payload): Json<CreateKnowledgeItemRequest>,
) -> Result<Json<CreateKnowledgeItemResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let tags_str = payload.tags.map(|t| serde_json::to_string(&t).unwrap_or_default());
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());

    task::spawn_blocking(move || {
        match db.create_knowledge_item(
            &payload.title,
            payload.content.as_deref(),
            &payload.item_type,
            payload.url.as_deref(),
            payload.file_path.as_deref(),
            payload.file_size,
            payload.mime_type.as_deref(),
            tags_str.as_deref(),
            metadata_str.as_deref(),
        ) {
            Ok(id) => Ok(Json(CreateKnowledgeItemResponse {
                id,
                message: format!("Knowledge item '{}' created successfully", payload.title),
            })),
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to create knowledge item: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn get_knowledge_item_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<KnowledgeItem>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.get_knowledge_item(id) {
        Ok(Some(item)) => Ok(Json(item)),
        Ok(None) => Err((
            StatusCode::NOT_FOUND,
            format!("Knowledge item with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to get knowledge item: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn list_knowledge_items_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<KnowledgeQuery>,
) -> Result<Json<KnowledgeItemListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || {
        match db.list_knowledge_items(params.item_type.as_deref(), params.limit, params.offset) {
            Ok(items) => {
                let total = items.len();
                Ok(Json(KnowledgeItemListResponse { items, total }))
            }
            Err(e) => Err((
                StatusCode::INTERNAL_SERVER_ERROR,
                format!("Failed to list knowledge items: {}", e),
            )),
        }
    })
    .await
    .unwrap()
}

pub async fn delete_knowledge_item_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.delete_knowledge_item(id) {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Knowledge item with id {} deleted successfully", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Knowledge item with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to delete knowledge item: {}", e),
        )),
    })
    .await
    .unwrap()
}

// Search handlers
pub async fn search_bookmarks_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<SearchQuery>,
) -> Result<Json<BookmarkListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.search_bookmarks(&params.q, params.limit) {
        Ok(bookmarks) => {
            let total = bookmarks.len();
            Ok(Json(BookmarkListResponse { bookmarks, total }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to search bookmarks: {}", e),
        )),
    })
    .await
    .unwrap()
}

pub async fn search_knowledge_items_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<SearchQuery>,
) -> Result<Json<KnowledgeItemListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.search_knowledge_items(&params.q, params.limit) {
        Ok(items) => {
            let total = items.len();
            Ok(Json(KnowledgeItemListResponse { items, total }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to search knowledge items: {}", e),
        )),
    })
    .await
    .unwrap()
}

// Vector search handlers
#[derive(Deserialize)]
pub struct VectorSearchQuery {
    pub q: String,
    pub limit: Option<usize>,
    pub agent_id: Option<i64>,
}

#[derive(Serialize)]
pub struct VectorSearchResponse {
    pub results: Vec<SearchResult>,
    pub total: usize,
    pub search_type: String,
}

pub async fn vector_search_knowledge_items_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<VectorSearchQuery>,
) -> Result<Json<VectorSearchResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let query = params.q.clone();
    let limit = params.limit;
    let agent_id = params.agent_id;

    match db.vector_search_knowledge_items_with_agent(&query, limit, agent_id).await {
        Ok(results) => {
            let total = results.len();
            Ok(Json(VectorSearchResponse {
                results,
                total,
                search_type: if agent_id.is_some() { "vector_with_agent".to_string() } else { "vector".to_string() },
            }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to perform vector search: {}", e),
        )),
    }
}

pub async fn fts_search_knowledge_items_handler(
    State(state): State<Arc<AppState>>,
    Query(params): Query<SearchQuery>,
) -> Result<Json<KnowledgeItemListResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    task::spawn_blocking(move || match db.search_knowledge_items_fts(&params.q, params.limit) {
        Ok(items) => {
            let total = items.len();
            Ok(Json(KnowledgeItemListResponse { items, total }))
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to perform FTS search: {}", e),
        )),
    })
    .await
    .unwrap()
}

// Enhanced knowledge item handlers with vector support
pub async fn create_knowledge_item_with_vector_handler(
    State(state): State<Arc<AppState>>,
    Json(payload): Json<CreateKnowledgeItemRequest>,
) -> Result<Json<CreateKnowledgeItemResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let tags_str = payload.tags.map(|t| serde_json::to_string(&t).unwrap_or_default());
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());
    let agent_id = payload.agent_id;

    match db.add_knowledge_item_with_vector_and_agent(
        &payload.title,
        payload.content.as_deref(),
        &payload.item_type,
        payload.url.as_deref(),
        payload.file_path.as_deref(),
        payload.file_size,
        payload.mime_type.as_deref(),
        tags_str.as_deref(),
        metadata_str.as_deref(),
        agent_id,
    ).await {
        Ok(id) => Ok(Json(CreateKnowledgeItemResponse {
            id,
            message: if agent_id.is_some() {
                format!("Knowledge item '{}' created with agent-based vector indexing", payload.title)
            } else {
                format!("Knowledge item '{}' created with vector indexing", payload.title)
            },
        })),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to create knowledge item with vector: {}", e),
        )),
    }
}

#[derive(Deserialize)]
pub struct UpdateKnowledgeItemRequest {
    pub title: Option<String>,
    pub content: Option<String>,
    pub tags: Option<Vec<String>>,
    pub metadata: Option<serde_json::Value>,
    pub agent_id: Option<i64>, // Agent ID for embedding configuration
}

#[axum::debug_handler]
pub async fn update_knowledge_item_with_vector_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
    Json(payload): Json<UpdateKnowledgeItemRequest>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    let tags_str = payload.tags.map(|t| serde_json::to_string(&t).unwrap_or_default());
    let metadata_str = payload.metadata.map(|m| serde_json::to_string(&m).unwrap_or_default());
    let agent_id = payload.agent_id;

    match db.update_knowledge_item_with_vector_and_agent(
        id,
        payload.title.as_deref(),
        payload.content.as_deref(),
        tags_str.as_deref(),
        metadata_str.as_deref(),
        agent_id,
    ).await {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: if agent_id.is_some() {
                format!("Knowledge item with id {} updated with agent-based vector re-indexing", id)
            } else {
                format!("Knowledge item with id {} updated with vector re-indexing", id)
            },
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Knowledge item with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to update knowledge item with vector: {}", e),
        )),
    }
}

pub async fn delete_knowledge_item_with_vector_handler(
    State(state): State<Arc<AppState>>,
    Path(id): Path<i64>,
) -> Result<Json<DeleteResponse>, (StatusCode, String)> {
    let db = state.database.clone();

    match db.delete_knowledge_item_with_vector(id).await {
        Ok(true) => Ok(Json(DeleteResponse {
            success: true,
            message: format!("Knowledge item with id {} deleted from database and vector store", id),
        })),
        Ok(false) => Err((
            StatusCode::NOT_FOUND,
            format!("Knowledge item with id {} not found", id),
        )),
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Failed to delete knowledge item with vector: {}", e),
        )),
    }
}

#[derive(Deserialize)]
pub struct BatchCreateKnowledgeRequest {
    pub items: Vec<BatchKnowledgeItem>,
}

#[derive(Deserialize)]
pub struct BatchKnowledgeItem {
    pub title: String,
    pub content: Option<String>,
    pub item_type: String,
    pub agent_id: Option<i64>, // Agent ID for embedding configuration
}

#[derive(Serialize)]
pub struct BatchCreateKnowledgeResponse {
    pub created_ids: Vec<i64>,
    pub total_created: usize,
    pub message: String,
}

pub async fn batch_create_knowledge_items_handler(
    State(state): State<Arc<AppState>>,
    Json(payload): Json<BatchCreateKnowledgeRequest>,
) -> Result<Json<BatchCreateKnowledgeResponse>, (StatusCode, String)> {
    let db = state.database.clone();
    
    // Group items by agent_id for batch processing
    let mut agent_groups: std::collections::HashMap<Option<i64>, Vec<(String, Option<String>, String)>> = std::collections::HashMap::new();
    
    for item in payload.items {
        let entry = agent_groups.entry(item.agent_id).or_insert_with(Vec::new);
        entry.push((item.title, item.content, item.item_type));
    }

    let mut all_created_ids = Vec::new();
    
    // Process each agent group separately
    for (agent_id, items) in agent_groups {
        match db.batch_add_knowledge_items_with_vector_and_agent(items, agent_id).await {
            Ok(mut created_ids) => {
                all_created_ids.append(&mut created_ids);
            }
            Err(e) => {
                return Err((
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Failed to batch create knowledge items for agent {:?}: {}", agent_id, e),
                ));
            }
        }
    }

    let total_created = all_created_ids.len();
    Ok(Json(BatchCreateKnowledgeResponse {
        created_ids: all_created_ids,
        total_created,
        message: format!("Successfully created {} knowledge items with agent-based vector indexing", total_created),
    }))
}
